<template>
  <div class="ComplexChart">
    <canvas width="2000" height="1000" id="canvas"></canvas>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted } from "vue";

const node = ref({
  title: "浙江省",
  children: [
    {
      title: "杭州市",
      children: [
        {
          title: "拱墅区",
          children: [
            {
              title: "北部软件园",
            },
          ],
        },
        {
          title: "余杭区",
          children: [
            {
              title: "梦想小镇",
            },
            {
              title: "欧美金融城",
            },
            {
              title: "华容科技城",
            }
          ]
        }
      ]
    },
    {
      title: "宁波市",
      children: [
        {
          title: "海曙区",
          children: [
            {
              title: "疆良小镇",
            },
            {
              title: "欧美金融城",
            },
          ],
        },
        {
          title: "江北区",
          children: [
            {
              title: "华兴小镇",
            },
            {
              title: "感电东方城",
            }
          ]
        }
      ]
    }
  ]
})

const render = (startX:any, startY:any, node:any) => {
  let nodeWidth = 100;
  let nodeHeight = 50;
  let nodeMargin = 12;

  drawTextItem({startX, startY, width: nodeWidth, height: nodeHeight, title: node.title});

  if(node.children && node.children.length>0){
    let count = 0;
    count = getAllCount(node);//计算最底层节点个数
    let start = startX - (nodeWidth*count+(nodeMargin*(count-1)))/2;//起点

    node.children.forEach((item: any, index:any) => {
      let childrenStartX = 0;
      let childrenStartY = startY+nodeMargin+nodeHeight;
      let nodeLenth = 0;

      if(item.children && item.children.length>0){
        nodeLenth= getAllCount(item)
      }else{
        nodeLenth = 1;
      }

      childrenStartX = start+(nodeWidth*nodeLenth+(nodeMargin*(nodeLenth-1)))/2;
      start = start+(nodeWidth*nodeLenth+(nodeMargin*(nodeLenth-1)))+nodeMargin;

      drawLine(startX,startY,childrenStartX,childrenStartY);//划线
      render(childrenStartX,childrenStartY,item);//划子级
    })
  }  

}

const drawTextItem = ({startX, startY, width, height, title}:any) => {
  let ctx = getCtx()
  // 重新开辟一个线路
  ctx.beginPath();
  // 画一个外边框
  ctx.rect(startX, startY, width, height);
  ctx.strokeStyle = "red";
  ctx.fillStyle = "pink";
  ctx.stroke();
  ctx.fill();

  // 写字
  ctx.fillStyle = "red";
  ctx.textBaseline = "middle";
  let { width:textWidth } = ctx.measureText(title);
  ctx.fillText(title, startX+(width-textWidth)/2, startY+height/2, textWidth);
}

const getCtx = () => {
  let cs:any = document.getElementById('canvas');
  let cxt = cs.getContext('2d');
  return cxt;
}

const getAllCount = (node:any) => {
  let count = 0
  node.children.reduce((pre:any, cue:any)=>{
    count = pre+(cue.children && cue.children.length>0?getAllCount(cue):1)
    return count;
  }, 0)

  return count
}

const drawLine = (nodeX:any,nodeY:any,childX:any,childY:any) => {
  let ctx = getCtx();
  let nodeWidth = 100;
  let nodeHeight = 50;
  let nodeMargin = 12;

  // 重新开辟一个线路
  ctx.beginPath();
  ctx.moveTo(nodeX+(nodeWidth/2),nodeY+nodeHeight);
  ctx.lineTo(nodeX+(nodeWidth/2),nodeY+nodeHeight+(nodeMargin/2));
  ctx.lineTo(childX+(nodeWidth/2),childY-(nodeMargin/2));
  ctx.lineTo(childX+(nodeWidth/2),childY);
  ctx.stroke() // 将起点和终点连接起来
}

const treeToArray = (tree:any) => {
  let result:any = [];
 
  function traverse(nodes: any, level:any) {
    if (!result[level]) result[level] = []; // 初始化级别数组
    nodes.forEach((node:any) => {
      result[level].push(node); // 将节点添加到当前级别的数组
      if (node.children && node.children.length) {
        traverse(node.children, level + 1); // 递归子节点
      }
    });
  }
 
  traverse([tree], 0); // 从根节点开始递归
  return result;
} 

onMounted(() => {
  render(500, 10, node.value)

  console.log(treeToArray(node.value))
})
</script>

<style lang="scss" scoped>
.ComplexChart {
  width: 100%;
  height: 100%;
  // #canvas {
  //   width: 1000px;
  //   height: 1000px;
  // }
}
</style>